﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using XMLSpreadGear.Attributes;
using XMLSpreadGear.Headers;
using System.Collections;
using System.Xml;
using XMLSpreadGear.Templates;
using System.Reflection;
using XMLSpreadGear.Core;

namespace XMLSpreadGear.ExcelEngine
{
    public class ExcelProcessorhh
    {
        private IList objdata;
        private Styles styles;
        private PropertyInfo[] props;
        private ExternalRow[] headers;
        private ExternalRow[] footers;

        public ExcelProcessorhh(IList data,Styles styles)
        {
            objdata = data;
            this.styles = styles;
        }

        public ExcelProcessorhh(IList data, Styles styles, ExternalRow[] documentHeaders):this(data,styles)
        {
            this.headers = documentHeaders;    
        }

        public ExcelProcessorhh(IList data, Styles styles, ExternalRow[] documentHeaders, ExternalRow[] documentFooters)
            : this(data, styles, documentHeaders)
        {
            this.footers = documentFooters;
        }

        public void Process()
        {
            XmlDocument exceldoc = new XmlDocument();
                XmlProcessingInstruction instruction;

                instruction = exceldoc.CreateProcessingInstruction("xml", "version='1.0'");
                exceldoc.AppendChild(instruction);

            instruction = exceldoc.CreateProcessingInstruction("mso-application", "progid='Excel.Sheet'");
            exceldoc.AppendChild(instruction);

            Workbook workbook = new Workbook("Workbook");
            workbook.DocumentProperties = new DocumentProperties("DocumentProperties", "Amit Kohad", "Amit Kohad", string.Empty, string.Empty);
            workbook.ExcelWorkbook = new ExcelWorkbook("ExcelWorkbook", 1000, 1500, 100, 100, false, false);
            workbook.Styles = styles;
            workbook.Worksheet = new Worksheet("Worksheet", "My book", false, false);
            exceldoc.AppendChild(exceldoc.ImportNode(workbook.GetElement().FirstChild,true));
            //exceldoc.InnerXml = workbook.ToString();
            XmlNode worksheetnode = exceldoc.GetElementsByTagName("Worksheet").OfType<XmlNode>().FirstOrDefault();
            worksheetnode.InnerXml = DefineTable().InnerXml;
            XmlNode tablenode = exceldoc.GetElementsByTagName("Table").OfType<XmlNode>().FirstOrDefault(); //exceldoc.SelectSingleNode(@"workbook\Worksheet\Table");
            tablenode.InnerXml = DefineColumns(exceldoc);



            tablenode.InnerXml = tablenode.InnerXml + DefineHeaderRow();

            foreach (object item in objdata)
            {
                tablenode.InnerXml = tablenode.InnerXml + DefineRows(item);
            }

           

            exceldoc.Save(@"d:\xml\myfile.xml");
        }

        private XmlDocument DefineTable()
        {
            Table table = new Table("Table");
            table.ExpandedColumnCount = GetColumnCount();
            table.ExpandedRowCount = (ulong) objdata.Count+1;
            return table.GetElement();
        }

        private ulong GetColumnCount()
        {
            if (objdata.Count > 0)
            {
                object obj = objdata[0];
                props = obj.GetType().GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.DeclaredOnly);
                return ulong.Parse(props.Count().ToString());
            }
            return 0;
        }

        private string DefineColumns(XmlDocument xdoc)
        {
            XmlNode node = xdoc.CreateNode(XmlNodeType.Element, "Columns", string.Empty);
            for (int i = 0; i < props.Count(); i++)
            {
                PropertyInfo info = props[i];
                object[] objattrs = info.GetCustomAttributes(typeof(CellTemplateAttribute), false);

                CellTemplateAttribute cellattribute = objattrs.OfType<CellTemplateAttribute>().FirstOrDefault();
                if (cellattribute != null)
                {
                    Column col = new Column("Column");
                    col.AutoFitWidth = cellattribute.AutoFitWidth;
                    //col.Caption = cellattribute.Caption;
                    col.Hidden = cellattribute.Hidden;
                    //col.Index = cellattribute.Index;
                    col.Span = cellattribute.Span;
                    //col.StyleID = cellattribute.StyleID;
                    //col.Width = cellattribute.Width;
                    node.InnerXml = node.InnerXml + col.ToString();
                }
            }
            
            return node.InnerXml;
        }

        private string DefineHeaderRow()
        {
            Row newrow = new Row("Row");
            newrow.AutoFitHeight = true;
            newrow.Cell = new Cell("Cell");
            for (int i = 0; i < props.Count(); i++)
            {
                PropertyInfo info = props[i];
                
                object[] objattrs = info.GetCustomAttributes(typeof(CellTemplateAttribute), false);
                
                CellTemplateAttribute cellattribute = objattrs.OfType<CellTemplateAttribute>().FirstOrDefault();

                if (cellattribute != null)
                {
                    Data datatype = new Data("Data", DataType.String);
                    datatype.Value = cellattribute.Caption;
                    
                    Cell cell = new Cell("Cell");
                    cell.Data = datatype;
                    cell.StyleID = cellattribute.StyleID;
                    
                    newrow.Cell.Add(cell);
                }
            }

            return newrow.ToString();
        }

        private string DefineRows(object objitem)
        {
            Row newrow = new Row("Row");
            newrow.AutoFitHeight = true;
            newrow.Cell = new Cell("Cell");
            foreach (PropertyInfo property in props)
            {
                Data datatype = new Data("Data",(DataType) Enum.Parse(typeof(DataType), property.PropertyType.Name, true));
                
                datatype.Value = ((property.GetValue(objitem, null) != null)? property.GetValue(objitem, null).ToString() : string.Empty);

                Cell cell = new Cell("Cell");
                cell.Data = datatype;
                
                object[] objattrs = property.GetCustomAttributes(typeof(CellTemplateAttribute), false);
                CellTemplateAttribute cellattribute = objattrs.OfType<CellTemplateAttribute>().FirstOrDefault();
                if (cellattribute != null)
                {
                    cell.StyleID = cellattribute.CellStyleID;
                }
                newrow.Cell.Add(cell);
            }
            

            return newrow.ToString();
        }
    }
}
